#[allow(unused_imports, deprecated)]
use std::ascii::AsciiExt;
use std::str::CharIndices;
use std::u16;

/// A Token returned from the `Lexer`.
///
/// Some variants may contains references to the original source text, so the `Token` has the same
/// lifetime as the source.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Token<'a> {
    Comment(&'a str),
    LPar,                  // '('
    RPar,                  // ')'
    LBrace,                // '{'
    RBrace,                // '}'
    LBracket,              // '['
    RBracket,              // ']'
    Minus,                 // '-'
    Plus,                  // '+'
    Multiply,              // '*'
    Comma,                 // ','
    Dot,                   // '.'
    Colon,                 // ':'
    Equal,                 // '='
    Not,                   // '!'
    Arrow,                 // '->'
    Float(&'a str),        // Floating point immediate
    Integer(&'a str),      // Integer immediate
    Type(types::Type),     // i32, f32, b32x4, ...
    DynamicType(u32),      // dt5
    Value(Value),          // v12, v7
    Block(Block),          // block3
    Cold,                  // cold (flag on block)
    StackSlot(u32),        // ss3
    DynamicStackSlot(u32), // dss4
    GlobalValue(u32),      // gv3
    Table(u32),            // table2
    Constant(u32),         // const2
    FuncRef(u32),          // fn2
    SigRef(u32),           // sig2
    UserRef(u32),          // u345
    UserNameRef(u32),      // userextname345
    Name(&'a str),         // %9arbitrary_alphanum, %x3, %0, %function ...
    String(&'a str),       // "arbitrary quoted string with no escape" ...
    HexSequence(&'a str),  // #89AF
    Identifier(&'a str),   // Unrecognized identifier (opcode, enumerator, ...)
    SourceLoc(&'a str),    // @00c7
}

/// A `Token` with an associated location.
#[derive(Debug, PartialEq, Eq)]
pub struct LocatedToken<'a> {
    pub token: Token<'a>,
    pub location: Location,
}

/// Wrap up a `Token` with the given location.
fn token(token: Token, loc: Location) -> Result<LocatedToken, LocatedError> {
    Ok(LocatedToken {
        token,
        location: loc,
    })
}

/// An error from the lexical analysis.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LexError {
    InvalidChar,
}

/// A `LexError` with an associated Location.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LocatedError {
    pub error: LexError,
    pub location: Location,
}

/// Wrap up a `LexError` with the given location.
fn error<'a>(error: LexError, loc: Location) -> Result<LocatedToken<'a>, LocatedError> {
    Err(LocatedError {
        error,
        location: loc,
    })
}